﻿//----------------------------------------------------------------
// Desc: 
// Edit: ShowLong, http://blog.csdn.net/showlong
//
// Date Created: 2012-04-13
//
// Update Date : 
//
// Copyright (c) Fuel4D (http://www.fuel4d.com), All rights reserved.
//
//----------------------------------------------------------------
#pragma once


//----------------------------------------------------------------
// 用于内存池的自动书写宏
//----------------------------------------------------------------
#define FUI_NEW_FUNC               const ACHAR* file, size_t line, const ACHAR* func, const ACHAR* name
#define FUI_NEW_FUNC_API           const ACHAR* file, size_t line, const ACHAR* func
#define FUI_NEW_PASS               file, line, func, name
#define FUI_NEW_PASS_API           file, line, func
#define FUI_NEW_INFO               _FFILEA_, _FLINEA_, _FFUNCA_


//----------------------------------------------------------------
//
//----------------------------------------------------------------
#define FUI_New(cls)               new(FUI_NEW_INFO, cls::_StaticClassName())  cls
#define FUI_NewAPI(cls)            new(FUI_NEW_PASS_API, cls::_StaticClassName()) cls
#define FUI_Alloc(t, n)            (t*)FUI_MemAlloc(sizeof(t)*(n), FUI_NEW_INFO, _FTA(#t))
#define FUI_Free(p)                FUI_MemFree((void*&)(p))
#define FUI_Realloc(p, t, n)       (t*)FUI_MemRealloc(p, sizeof(t)*(n), FUI_NEW_INFO, _FTA(#t))


//----------------------------------------------------------------
// placement 分配
//----------------------------------------------------------------
#define FUI_NewPT(p, cls)          ::new(p) cls
#define FUI_NewPP(p)               ::new(p)


//----------------------------------------------------------------
// 释放
//----------------------------------------------------------------
template < typename _Ty > FINLINE void FUI_Del(_Ty*& p){ if (p) { delete p; p = 0; } }
template < typename _Ty > FINLINE void FUI_DelArray(_Ty*& p){ if (p) { delete[] p; p = 0; } }
template < typename _Ty > FINLINE void FUI_DelRelease(_Ty*& p){ if (p) { p->Release(); delete p; p = 0; } }
template < typename _Ty > FINLINE void FUI_DelDestory(_Ty*& p){ if (p != 0) { p->Destroy(); delete p; p = 0; } }
template < typename _Ty > FINLINE void FUI_Release(_Ty*& p){ if (p != 0) { p->Release(); p = 0; } }
template < typename _Ty > FINLINE void FUI_Destory(_Ty*& p){ if (p != 0) { p->Destroy(); p = 0; } }


//----------------------------------------------------------------
// 用于IFMemObjectNEW/DELETE操作符代码
//----------------------------------------------------------------
#define FUI_DECLARE_NEW \
public:\
    FINLINE static void* operator new  (size_t size, FUI_NEW_FUNC){ return FUI_MemAlloc(size, FUI_NEW_PASS); }\
    FINLINE static void* operator new[](size_t size, FUI_NEW_FUNC){ return FUI_MemAlloc(size, FUI_NEW_PASS); }\
    FINLINE static void operator delete  (void* pm, FUI_NEW_FUNC){ FUI_Free(pm); }\
    FINLINE static void operator delete[](void* pm, FUI_NEW_FUNC){ FUI_Free(pm); }\
private:\
    FINLINE static void* operator new  (size_t size){ return FUI_MemAlloc(size, FUI_NEW_INFO, _FTA("<error>")); }\
    FINLINE static void* operator new[](size_t size){ return FUI_MemAlloc(size, FUI_NEW_INFO, _FTA("<error>")); }\
public:\
    FINLINE static void operator delete  (void* pm){ FUI_Free(pm); }\
    FINLINE static void operator delete[](void* pm){ FUI_Free(pm); }


//----------------------------------------------------------------
// 普通小结构体重载NEW/DELETE，提供给那些不需要从IFMemObject继承的对象
//----------------------------------------------------------------
#define FUI_DECLARE_STRUCT(class_name) \
public:\
    FUI_DECLARE_NEW;\
public:\
    static const ACHAR* _StaticClassName(){ return _FTA(#class_name); }


//----------------------------------------------------------------
// 从IFMemObject基类派生的最终层类对象实现
//----------------------------------------------------------------
#define FUI_DECLARE_CLASS(class_name) \
public:\
    virtual const ACHAR* ClassName(){ return _StaticClassName(); }\
    virtual FIDHASH ClassHash(){ return (FIDHASH)(DWORD_PTR)&_StaticClassName; }\
    static const ACHAR* _StaticClassName(){ return _FTA(#class_name); }


//----------------------------------------------------------------
// 内存操作
//----------------------------------------------------------------
extern FAPI void* FUI_MemAlloc(size_t sz, FUI_NEW_FUNC);
extern FAPI void* FUI_MemRealloc(void* p, size_t sz, FUI_NEW_FUNC);
extern FAPI void FUI_MemFree(void*& p);


//----------------------------------------------------------------
//
//----------------------------------------------------------------
class IFUI_MemObject
{
protected:
    explicit IFUI_MemObject()
    {}

public:
    // 必须存在的虚析构
    virtual~IFUI_MemObject()
    {}
    // 获取本对象的类名
    virtual const ACHAR* ClassName() = 0;
    // 获取本对象的类名HASH
    virtual FIDHASH ClassHash() = 0;
    // 判断当前对象是否与P是同一个类型的（完整匹配）
    virtual bool IsKind(IFUI_MemObject* p){ return p->ClassHash() == this->ClassHash(); }
    // 测试是我自己是否是指定的类型（完整匹配）
    template< typename _Ty >
    FINLINE bool IsClass(){ return (FIDHASH)(DWORD_PTR)&_Ty::_StaticClassName == this->ClassHash(); }

    FUI_DECLARE_NEW;
};

template < typename _Ty >
class IFUI_Instance : public IFUI_MemObject
{
    static _Ty* fclass_instance;

protected:
    IFUI_Instance()
    {
        assert(!fclass_instance);
        if (!fclass_instance)
            fclass_instance = (_Ty*)this;
    }
    IFUI_Instance(const IFUI_Instance&){}
    IFUI_Instance& operator=(const IFUI_Instance&){ return *this; }

public:
    virtual~IFUI_Instance()
    {
        assert(fclass_instance);
        fclass_instance = 0;
    }
    // 测试是否已经创建了实例了
    static bool IsInitialize()
    {
        return fclass_instance != 0;
    }
    // 获取实例地址
    static _Ty* Instance()
    {
        assert(fclass_instance && _FT("没有找到实体内存地址"));
        return fclass_instance;
    }
    // 获取实例对象
    static _Ty& GetInstance()
    {
        assert(fclass_instance && _FT("没有找到实体内存地址"));
        return *fclass_instance;
    }
};

template <typename _Ty>
_Ty* IFUI_Instance<_Ty>::fclass_instance = 0;
